#include "Dream.h"
#include "Universe.h"
#include <QDir>
#include <QDateTime>
#include <QProcess>
Dream::Dream(Universe* master,int handle):Master(master),isAlive(true),isConnected(false),mBlockSize(0)
{
    mSocket= new QSslSocket(this);
    connect(mSocket, SIGNAL(readyRead()), this, SLOT(OnReceiveDataBlock()));
    connect(mSocket, SIGNAL(connected()), this, SLOT(OnConnect()));
    connect(mSocket, SIGNAL(disconnected()), this, SLOT(OnDisconnect()));
    connect(mSocket, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(OnError(QAbstractSocket::SocketError)));
   bool val= mSocket->setSocketDescriptor(handle);



     sessionId.Create(BIT256);
     DataBlock encoded;
    sprng_read(sessionId.Get(),BIT256,0);

    mCrypter.encode(Base64,sessionId,encoded);
    Json::Value root(Json::objectValue);

    root["jsonrpc"]="2.0";
    root["method"]="login";
    root["params"]["sessionId"]=std::string((char*)encoded.Get());
    Json::FastWriter writer;
    SendMessage(writer.write(root));

}

Dream::~Dream()
{
    delete mSocket;
}

void Dream::SendMessage(const std::string& data)
{
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    quint32 len=data.length();

    for(int i=0;i<sizeof(quint32);i++)
        mSocket->write(((char*)&len)+3-i,1);
    int written= mSocket->write(data.c_str(),data.length());
}
void Dream::OnConnect()
{
    isConnected=true;
}

void Dream::OnDisconnect()
{
    isConnected=false;
    isAlive=false;
}
void Dream::OnReceiveDataBlock()
{

    if(!mBlockSize)
    {
        if(mSocket->bytesAvailable()<sizeof(quint32))
            return;
        else
          {
            for(int i=0;i<sizeof(quint32);i++)
                mSocket->read(((char*)&mBlockSize)+3-i,1);// прочли размер пакета
         }
     }
    if(mBlockSize)
    {
        quint32 avail = mSocket->bytesAvailable();
        if(avail<mBlockSize)
            return;
        else
        {
            char* data=new char[mBlockSize+1];
             data[mBlockSize]=0;
             mSocket->read(data,mBlockSize);

             Json::Reader reader;
             Json::Value root;

             bool success=reader.parse(data,root,false);


                OnRequest(root);
                mBlockSize=0;
                OnReceiveDataBlock();

         }

    }

}
bool Dream::LoadKey(DataBlock& key,const std::string& user,const std::string& type)
{
    QString filename("key_");
    filename+=type.c_str();
    QString appPath=Master->GetAppPath(true);
    appPath+=user.c_str();
    #ifdef WIN32
         filename=appPath+"\\"+filename+".dat";
     #else
         filename=appPath+"/"+filename+".dat";
    #endif


    QFile f(filename);
    bool val= f.open(QFile::ReadOnly);
    if(val)
     {
        QString err=f.errorString();
        key.Create(f.size());
        f.read((char*)key.Get(),f.size());
        f.close();
        char a;a=0;
        key.Add((unsigned char*)&a,1);
        return true;
    }
    else
        return false;
}

void Dream::SaveKey(const std::string& user,const std::string& key,const std::string& type)
{
    QString filename("key_");
    filename+=type.c_str();


    QString appPath=Master->GetAppPath(false);
#ifdef WIN32
    QString msg("\\EchoServer\\");
 #else
    QString msg("/EchoServer/");
#endif

    QDir app(appPath+msg),dir(appPath);
    if(!app.exists())
    {
        bool success = dir.mkdir("EchoServer");
    }
    QDir appKey(appPath+msg+user.c_str()),appUser(appPath+msg);
    if(!appKey.exists())
        bool success = appUser.mkdir(user.c_str());

    #ifdef WIN32
    filename=appPath+msg+user.c_str()+"\\"+filename+".dat";
     #else
    filename=appPath+msg+user.c_str()+"/"+filename+".dat";
    #endif




    QFile f(filename);
    bool val= f.open(QFile::ReadWrite);
    QString err=f.errorString();
    quint64 size=f.write(key.c_str(),key.length());
    f.close();
}

 void Dream::OnRequest(Json::Value& root)
 {
     if(root["method"]=="authorizationAsk")
     {
         Json::Value answer;
         answer["jsonrpc"]="2.0";
         answer["id"]=root["id"];
         Json::FastWriter writer;
         SendMessage(writer.write(answer));
         SaveKey(mName.toStdString(),root["params"]["sendKey"]["keyEncrypted"].asString(),
                 std::string("sendto_")+root["params"]["userId"].asString());
         SaveKey(mName.toStdString(),root["params"]["sendKey"]["keyEncryptedForMe"].asString(),
                 std::string("sendto_forme_")+root["params"]["userId"].asString());
         SaveKey(mName.toStdString(),root["params"]["sendKey"]["keySignature"].asString(),
                 std::string("sendto_sign_")+root["params"]["userId"].asString());
         Master->SendNotif("authorizationAsk",mName,root);

     }
     if(root["method"]=="chatKeyGet")
     {
         Json::Value answer;
         answer["jsonrpc"]="2.0";
         answer["id"]=root["id"];

         DataBlock senderforme,sendersign;

         LoadKey(senderforme,mName.toStdString(),
                 std::string("sendto_forme_")+root["params"]["userId"].asString());
         LoadKey(sendersign,mName.toStdString(),
                 std::string("sendto_sign_")+root["params"]["userId"].asString());

         DataBlock rec,recsign;

         LoadKey(rec,root["params"]["userId"].asString(),
                 std::string("sendto_")+mName.toStdString());

         LoadKey(recsign,root["params"]["userId"].asString(),
                 std::string("sendto_sign_")+mName.toStdString());

         answer["result"]["receiveKeyEncrypted"] = string((char*)rec.Get()).c_str();
         answer["result"]["receiveKeySignature"] = string((char*)recsign.Get()).c_str();
         answer["result"]["sendKeyEncryptedForMe"] = string((char*)senderforme.Get()).c_str();
         answer["result"]["sendKeySignature"] = string((char*)sendersign.Get()).c_str();

         Json::FastWriter writer;
         SendMessage(writer.write(answer));
     }
     if(root["method"]=="authorizationConfirm")
     {
         Json::Value answer;
         answer["jsonrpc"]="2.0";
         answer["id"]=root["id"];
         Json::FastWriter writer;
         SendMessage(writer.write(answer));
         SaveKey(mName.toStdString(),root["params"]["sendKey"]["keyEncrypted"].asString(),
                 std::string("sendto_")+root["params"]["userId"].asString());
         SaveKey(mName.toStdString(),root["params"]["sendKey"]["keyEncryptedForMe"].asString(),
                 std::string("sendto_forme_")+root["params"]["userId"].asString());
         SaveKey(mName.toStdString(),root["params"]["sendKey"]["keySignature"].asString(),
                 std::string("sendto_sign_")+root["params"]["userId"].asString());
         Master->SendNotif("authorizationConfirm",mName,root);

     }
     if(root["method"]=="messageSend")
     {
         Json::Value answer;
         answer["jsonrpc"]="2.0";
         answer["id"]=root["id"];
         Json::FastWriter writer;
         SendMessage(writer.write(answer));

         Master->SendNotif("message",mName,root);

     }
     if(root["method"]=="userRequestVerify")
     {
         Json::Value answer;
         answer["jsonrpc"]="2.0";
         answer["id"]=root["id"];
         answer["result"]="code sent";
         Json::FastWriter writer;
         SendMessage(writer.write(answer));
     }
     /*
     if(root["method"]=="setPass")
     {
         DataBlock key;
         key.CreateFrom((unsigned char*)root["params"]["privateKeyEncrypted"].asString().c_str(),
                 root["params"]["privateKeyEncrypted"].asString().length());
         int key_len=root["params"]["len"].asInt();
         mCrypter.decode(Base64,key,key);

         publicCipher.CreateFrom(key.Get(),key_len);
         publicSign.CreateFrom(key.Get()+key_len,key.GetLength()-key_len);

         mCrypter.AcceptRSAKeys(publicCipher,publicSign);

     }*/
     if(root["method"]=="userRegister")
     {
         if(!Master->HasUser(root["params"]["userId"].asString()))
         {
             publicCipher.CreateFrom((unsigned char*)root["params"]["encryptionKey"].asString().c_str(),
                     root["params"]["encryptionKey"].asString().length());
             publicSign.CreateFrom((unsigned char*)root["params"]["signatureKey"].asString().c_str(),
                     root["params"]["signatureKey"].asString().length());
             mCrypter.decode(Base64,publicCipher,publicCipher);
             mCrypter.decode(Base64,publicSign,publicSign);
             mCrypter.AcceptRSAKeys(publicCipher,publicSign);
             Json::Value answer;
             answer["jsonrpc"]="2.0";
             answer["id"]=root["id"];
             answer["result"]["userId"]=root["params"]["userId"];
             Json::FastWriter writer;
             SendMessage(writer.write(answer));

             SaveKey(root["params"]["userId"].asString(),
                     root["params"]["privateKeyEncrypted"].asString(),
                     "private");
             SaveKey(root["params"]["userId"].asString(),
                     root["params"]["encryptionKey"].asString(),
                     "public_enc");
             SaveKey(root["params"]["userId"].asString(),
                     root["params"]["signatureKey"].asString(),
                     "public_sign");
         }
         else
         {
             Json::Value answer;
             answer["jsonrpc"]="2.0";
             answer["id"]=root["id"];
             answer["error"]["code"]="-103";
             answer["error"]["message"]="User already registered";
             Json::FastWriter writer;
             SendMessage(writer.write(answer));
         }
     }
     if(root["method"]=="userResetKey")
     {
         publicCipher.CreateFrom((unsigned char*)root["params"]["encryptionKey"].asString().c_str(),
                 root["params"]["encryptionKey"].asString().length());
         publicSign.CreateFrom((unsigned char*)root["params"]["signatureKey"].asString().c_str(),
                 root["params"]["signatureKey"].asString().length());
         mCrypter.decode(Base64,publicCipher,publicCipher);
         mCrypter.decode(Base64,publicSign,publicSign);
         mCrypter.AcceptRSAKeys(publicCipher,publicSign);
         Json::Value answer;
         answer["jsonrpc"]="2.0";
         answer["id"]=root["id"];
         answer["result"]["userId"]=root["params"]["userId"];
         Json::FastWriter writer;
         SendMessage(writer.write(answer));
         SaveKey(root["params"]["userId"].asString(),
                 root["params"]["privateKeyEncrypted"].asString(),
                 "private");
         SaveKey(root["params"]["userId"].asString(),
                 root["params"]["encryptionKey"].asString(),
                 "public_enc");
         SaveKey(root["params"]["userId"].asString(),
                 root["params"]["signatureKey"].asString(),
                 "public_sign");
     }
     if(root["method"]=="privateKeyGet")
     {
         DataBlock key;
         LoadKey(key,root["params"]["userId"].asString(),"private");
         char a=0;
         key.Add((unsigned char*)&a,1);
         Json::Value answer;
         answer["jsonrpc"]="2.0";
         answer["id"]=root["id"];
         answer["result"]["privateKeyEncrypted"]=string((char*)key.Get()).c_str();
         Json::FastWriter writer;
         SendMessage(writer.write(answer));

     }
     if(root["method"]=="publicKeyGet")
     {
         DataBlock key_enc,key_sign;
         if(LoadKey(key_enc,root["params"]["userId"].asString(),"public_enc") &&
         LoadKey(key_sign,root["params"]["userId"].asString(),"public_sign"))
         {
             char a=0;
             key_enc.Add((unsigned char*)&a,1);
             key_sign.Add((unsigned char*)&a,1);
             Json::Value answer;
             answer["jsonrpc"]="2.0";
             answer["id"]=root["id"];
             answer["result"]["encryptionKey"]=string((char*)key_enc.Get()).c_str();
             answer["result"]["signatureKey"]=string((char*)key_sign.Get()).c_str();
             Json::FastWriter writer;
             SendMessage(writer.write(answer));
        }
         else
         {
             Json::Value answer;
             answer["jsonrpc"]="2.0";
             answer["id"]=root["id"];
             answer["error"]["code"]="-103";
             answer["error"]["message"]="User not found";
             Json::FastWriter writer;
             SendMessage(writer.write(answer));
         }
     }
     if(root["method"]=="userLogin")
     {
         DataBlock session_verify;

         if(LoadKey(publicCipher,root["params"]["userId"].asString(),"public_enc") && LoadKey(publicSign,root["params"]["userId"].asString(),"public_sign"))
         {
             mCrypter.decode(Base64,publicCipher,publicCipher);
             mCrypter.decode(Base64,publicSign,publicSign);
             mCrypter.AcceptRSAKeys(publicCipher,publicSign);
             session_verify.CreateFrom((unsigned char*)root["params"]["signature"].asString().c_str(),
               root["params"]["signature"].asString().length());
             mCrypter.decode(Base64,session_verify,session_verify);
             int correct;
             mCrypter.verifySign(session_verify,sessionId,correct);
             if(correct)
             {
                 Json::Value answer;
                 answer["jsonrpc"]="2.0";
                 answer["id"]=root["id"];
                 answer["result"]["userId"]=root["params"]["userId"];
                 Json::FastWriter writer;
                 SendMessage(writer.write(answer));
                 mName=root["params"]["userId"].asString().c_str();

             }
             else
             {
                 Json::Value answer;
                 answer["jsonrpc"]="2.0";
                 answer["id"]=root["id"];
                 answer["error"]["code"]="-101";
                 answer["error"]["message"]="Wrong auth";
                 Json::FastWriter writer;
                 SendMessage(writer.write(answer));
             }
          }
         else
         {
             Json::Value answer;
             answer["jsonrpc"]="2.0";
             answer["id"]=root["id"];
             answer["error"]["code"]="-103";
             answer["error"]["message"]="User not found";
             Json::FastWriter writer;
             SendMessage(writer.write(answer));
         }
     }
 }
 void Dream::OnError(QAbstractSocket::SocketError socketError)
 {

 }
